#include "SharedMemory.h"
#include <QVector>
SharedMemory SharedMemory::sInst;

#define MEM_TRY_LOCK_MS 500

class SharedMemoryPrivate{
public:
    friend class SharedMemory;

    QReadWriteLock mMemLocker;
    QHash<QString,MemeryItem*> mMem;
};


MemError SharedMemory::GetMemItemWriteLock(QString name, MemeryItem **item)
{
    if(!_p->mMemLocker.tryLockForWrite(MEM_TRY_LOCK_MS)){
        return GetLockFailed;
    }

    if(!_p->mMem.contains(name)){
        _p->mMemLocker.unlock();
        return NotExist;
    }

    *item = _p->mMem[name];
    if(!(*item)->locker.tryLockForWrite(MEM_TRY_LOCK_MS)){
        _p->mMemLocker.unlock();
        return GetLockFailed;
    }

    return OK;
}

MemError SharedMemory::CreateMemP(QString name, void *handle)
{
    if(!_p->mMemLocker.tryLockForWrite(MEM_TRY_LOCK_MS)){
        _p->mMemLocker.unlock();
        return GetLockFailed;
    }

    if(_p->mMem.contains(name) && _p->mMem[name]->data != nullptr){
        _p->mMemLocker.unlock();
        return Exist;
    }

    MemeryItem* mi = new MemeryItem;
    mi->data = handle;
    mi->name = name;

    _p->mMem.insert(name,mi);

    _p->mMemLocker.unlock();
    return OK;
}

MemError SharedMemory::GetMemReadLock(QString name, const void **phandle)
{
    if(!_p->mMemLocker.tryLockForRead(MEM_TRY_LOCK_MS)){
        return GetLockFailed;
    }

    if(!_p->mMem.contains(name) || _p->mMem[name]->data == nullptr){
        _p->mMemLocker.unlock();
        return NotExist;
    }

    auto item = _p->mMem[name];
    if(!item->locker.tryLockForRead(MEM_TRY_LOCK_MS)){
        _p->mMemLocker.unlock();
        return GetLockFailed;
    }

    (*phandle) = item->data;


    return OK;
}

MemError SharedMemory::GetMemWriteLock(QString name, void **phandle)
{
    if(!_p->mMemLocker.tryLockForRead(MEM_TRY_LOCK_MS)){
        return GetLockFailed;
    }

    if(!_p->mMem.contains(name) || _p->mMem[name]->data == nullptr){
        _p->mMemLocker.unlock();
        return NotExist;
    }

    auto item = _p->mMem[name];
    if(!item->locker.tryLockForWrite(MEM_TRY_LOCK_MS)){
        _p->mMemLocker.unlock();
        return GetLockFailed;
    }

    *phandle = item->data;

    return OK;
}

MemError SharedMemory::UnlockMem(QString name)
{
    if(!_p->mMem.contains(name) || _p->mMem[name]->data != nullptr){
        _p->mMemLocker.unlock();
        return NotExist;
    }
\
    auto item = _p->mMem[name];
    item->locker.unlock();
    _p->mMemLocker.unlock();

    return OK;

}

MemError SharedMemory::RemoveMemItem(QString name)
{
   _p->mMem.remove(name);

   return OK;
}

SharedMemory::SharedMemory():_p(new SharedMemoryPrivate)
{

}

SharedMemory::~SharedMemory()
{
    if(_p){
        delete _p;
        _p = nullptr;
    }
}




